import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Dependencies,
} from "@nestjs/common";
import { FastifyRequest } from "fastify";
import { Observable, of } from "rxjs";
import { tap } from "rxjs/operators";
import { PrismaClient } from "@prisma/client";

import { WebResult } from "src/common/web.result";
import configuration from "src/common/configuration";
import { UserTokenService } from "src/user/token.service";

@Injectable()
@Dependencies(PrismaClient, UserTokenService)
export class AdminLoginInterceptor implements NestInterceptor {
  constructor(
    private readonly prisma: PrismaClient,
    private readonly userTokenService: UserTokenService,
  ) {}

  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<any> | Promise<Observable<any>> {
    return new Promise(async (resolve) => {
      const now = Date.now();

      const request: FastifyRequest = context.switchToHttp().getRequest();
      const token = this.userTokenService.getTokenFromRequest(request);
      if (!token) {
        resolve(of(WebResult.failure(undefined, "token is null")));
        return;
      }

      console.log("验证管理员token", token);
      const userData = this.userTokenService.getUserDataFromToken(token);
      if (!userData || !userData.id || !userData.username) {
        resolve(of(WebResult.failure(undefined, "token is wrong")));
        return;
      }

      const user = await this.prisma.user.findUnique({
        select: {
          id: true,
          password: true,
        },
        where: {
          id: userData.id,
          username: userData.username,
        },
      });
      if (!user) resolve(of(WebResult.failure(undefined, "不存在的用户")));

      // 判断是否管理员
      if (
        !configuration.user ||
        !configuration.user.administrators.includes(userData.username)
      ) {
        resolve(of(WebResult.failure(undefined, "权限不足")));
        return;
      }
      console.log("administrator");

      try {
        await this.userTokenService.verifyToken(token, user.password);
        resolve(
          next
            .handle()
            .pipe(tap(() => console.log(`After... ${Date.now() - now}ms`))),
        );
      } catch (e) {
        console.error(e);
        resolve(of(WebResult.failure(undefined, "权限不足")));
      }
    });
  }
}
